#include "rtspctrl.h"
#include <QtWidgets>
#include <QtConcurrent>
#include <QFuture>
#include <chrono>

RtspCtrl::RtspCtrl(QObject *parent)
    : QObject{parent}
{
    InitThread();
}

RtspCtrl::~RtspCtrl()
{
    m_state = ThreadState::IDLE_STATE;
    m_exit = true;
    m_cv.notify_all();
    m_connected = false;
    if(m_work_thread.joinable())m_work_thread.join();
}


void RtspCtrl::InitThread()
{
    m_work_thread = std::thread([this]{
        std::unique_lock<std::mutex>loc(m_cv_mutex);
        while(!m_exit)
        {
            switch(m_state)
            {
            case ThreadState::IDLE_STATE:
            {
                m_cv.wait_for(loc,std::chrono::milliseconds(200),[this]{return m_exit;});
                continue;
            }
                break;
            case ThreadState::CACULATE_STATE:
            {
                    cv::Mat frame;
                    {
                        std::lock_guard<std::mutex>loc(m_mutex);
                        if (cap.read(frame)) {
                            // 保存最后一帧
                            m_lastFrame = frame.clone();
                            cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
                            QImage img(frame.data, frame.cols, frame.rows,
                                       frame.step, QImage::Format_RGB888);
                            emit signal_update_image(img);
                        }
                    }

                m_cv.wait_for(loc,std::chrono::milliseconds(30),[this]{return m_exit;});
            }
                break;
            default:
                break;
            }//switch
        }
    });
}

void RtspCtrl::FinishedInit(bool ok)
{
    emit signal_init_result(ok);
    m_connected = ok;
    if(!ok)return;
    m_state = ThreadState::CACULATE_STATE;
}

void RtspCtrl::DoOpen(const QString& uri)
{
#ifdef __x86_64
    qputenv("OPENCV_FFMPEG_CAPTURE_OPTIONS","rtsp_transport;tcp|stimeout;500000|probesize;32768|analyzeduration;0");
    cap.open(uri.toStdString(),cv::CAP_FFMPEG);
    qunsetenv("OPENCV_FFMPEG_CAPTURE_OPTIONS");
#elif __aarch64__
    cap.open(uri.toStdString());
#endif
}

void RtspCtrl::InitRtsp(const QString&uri,QLabel* show_widget)
{
    m_show_wid = show_widget;
    QFuture<void>fut = QtConcurrent::run(this,&RtspCtrl::DoOpen,uri);
    QFutureWatcher<void>*watcher = new QFutureWatcher<void>(this);
    connect(watcher,&QFutureWatcher<void>::finished,this,[this,watcher]{
        bool ok = cap.isOpened();
        FinishedInit(ok);
        watcher->deleteLater();
    });
    watcher->setFuture(fut);
}

void RtspCtrl::GrabPic()
{
    cv::Mat frame;
    {
        std::lock_guard<std::mutex> loc(m_mutex);
        if(cap.read(frame)) {
            QString fn = QDateTime::currentDateTime()
                    .toString("yyyyMMdd_hhmmss") + ".jpg";
            cv::imwrite(fn.toStdString(), frame);
            qDebug() << "saved" << fn;
        }
    }
}

bool RtspCtrl::GrapPic(const QString&pic_name)
{
    if(pic_name.isEmpty())
        return false;
    cv::Mat frameCopy;
    {
        std::lock_guard<std::mutex> loc(m_mutex);
        if (m_lastFrame.empty())
            return false;

        // 复制最后一帧
        frameCopy = m_lastFrame.clone();
    }
    // 保存图片（不需要在互斥锁内进行IO操作）
    cv::imwrite(pic_name.toStdString(), frameCopy);
    qDebug() << "saved" << pic_name;
    return true;
}

void RtspCtrl::PlayRtsp()
{
    if(m_connected)
        m_state = ThreadState::CACULATE_STATE;
}

void RtspCtrl::StopRtsp()
{
    if(m_connected)
        m_state = ThreadState::IDLE_STATE;
}
